﻿using System;
using System.ComponentModel;
using System.Data;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using PCSComMaterials.Inventory.BO;
using PCSComUtils.Common;
using PCSComUtils.Common.BO;
using PCSComUtils.DataContext;
using PCSComUtils.PCSExc;
using PCSUtils.Log;
using PCSUtils.Utils;

namespace PCSMaterials.Inventory
{
    public partial class StockTakingPeriod : Form
    {
        private const string This = "PCSMaterials.Inventory.StockTakingPeriod";
        private readonly UtilsBO _boUtil = new UtilsBO();
        private EnumAction _formMode;
        private Thread _updateThread;

        public StockTakingPeriod()
        {
            InitializeComponent();
        }

        #region Event handlers

        private void StockTakingPeriod_Load(object sender, EventArgs e)
        {
            const string methodName = This + ".StockTakingPeriod_Load()";
            try
            {
                //Set authorization for user
                var objSecurity = new Security();
                Name = This;
                if (objSecurity.SetRightForUserOnForm(this, SystemProperty.UserName) == 0)
                {
                    Close();
                    // You don't have the right to view this item
                    PCSMessageBox.Show(ErrorCode.MESSAGE_YOU_HAVE_NO_RIGHT_TO_VIEW, MessageBoxIcon.Warning);
                    return;
                }
                // Load combo box
                DataSet dstCCN = _boUtil.ListCCN();
                CCNSelector.DataSource = dstCCN.Tables[MST_CCNTable.TABLE_NAME];
                CCNSelector.DisplayMember = MST_CCNTable.CODE_FLD;
                CCNSelector.ValueMember = MST_CCNTable.CCNID_FLD;
                FormControlComponents.PutDataIntoC1ComboBox(CCNSelector, dstCCN.Tables[MST_CCNTable.TABLE_NAME],
                                                            MST_CCNTable.CODE_FLD, MST_CCNTable.CCNID_FLD,
                                                            MST_CCNTable.TABLE_NAME);
                if (SystemProperty.CCNID != 0)
                {
                    CCNSelector.SelectedValue = SystemProperty.CCNID;
                }

                FromDatePicker.CustomFormat = Constants.DATETIME_FORMAT_HOUR;
                ToDatePicker.CustomFormat = Constants.DATETIME_FORMAT_HOUR;

                //switch form mode
                _formMode = EnumAction.Default;
                SwitchFormMode();
                UpdateInventoryButton.Enabled = false;
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void PeriodText_Validating(object sender, CancelEventArgs e)
        {
            const string methodName = This + ".PeriodText_Validating()";
            try
            {
                if (PeriodButton.Enabled)
                {
                    if (!PeriodText.Modified)
                        return;
                    if (PeriodText.Text == string.Empty)
                    {
                        FillPeriodData(null);
                        return;
                    }
                    DataRowView drwResult = FormControlComponents.OpenSearchForm(IV_StockTakingPeriodTable.TABLE_NAME,
                                                                                 IV_StockTakingPeriodTable.
                                                                                     DESCRIPTION_FLD,
                                                                                 PeriodText.Text.Trim(), null, false);
                    if (drwResult != null)
                    {
                        FillPeriodData(drwResult);
                    }
                    else
                    {
                        e.Cancel = true;
                    }
                }
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void PeriodText_KeyDown(object sender, KeyEventArgs e)
        {
            if (PeriodButton.Enabled && e.KeyCode == Keys.F4)
            {
                PeriodButton_Click(null, null);
            }
        }

        private void PeriodButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".PeriodButton_Click()";
            try
            {
                DataRowView drwResult = FormControlComponents.OpenSearchForm(IV_StockTakingPeriodTable.TABLE_NAME,
                                                                             IV_StockTakingPeriodTable.DESCRIPTION_FLD,
                                                                             PeriodText.Text.Trim(), null, true);
                if (drwResult != null)
                {
                    FillPeriodData(drwResult);
                }
                else
                {
                    PeriodText.Focus();
                }
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void WorkingPeriodText_Validating(object sender, CancelEventArgs e)
        {
            const string methodName = This + ".WorkingPeriodText_Validating()";
            try
            {
                if (WorkingPeriodButton.Enabled)
                {
                    if (!WorkingPeriodText.Modified)
                        return;
                    if (WorkingPeriodText.Text == string.Empty)
                    {
                        WorkingPeriodText.Tag = null;
                        WorkingPeriodLabel.Tag = null;
                        WorkingPeriodButton.Tag = null;
                        return;
                    }
                    DataRowView drwResult = FormControlComponents.OpenSearchForm(Sys_PeriodTable.TABLE_NAME,
                                                                                 Sys_PeriodTable.FROMDATE_FLD,
                                                                                 WorkingPeriodText.Text.Trim(), null,
                                                                                 false);
                    if (drwResult != null)
                    {
                        WorkingPeriodText.Text =
                            ((DateTime) drwResult[Sys_PeriodTable.FROMDATE_FLD]).ToString(Constants.DATETIME_FORMAT);
                        WorkingPeriodText.Tag = drwResult[Sys_PeriodTable.PERIODID_FLD];
                        WorkingPeriodLabel.Tag = drwResult[Sys_PeriodTable.TODATE_FLD];
                        WorkingPeriodButton.Tag = drwResult[Sys_PeriodTable.FROMDATE_FLD];
                    }
                    else
                    {
                        e.Cancel = true;
                    }
                }
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void WorkingPeriodText_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F4 && WorkingPeriodButton.Enabled)
            {
                WorkingPeriodButton_Click(null, null);
            }
        }

        private void WorkingPeriodButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".WorkingPeriodButton_Click()";
            try
            {
                DataRowView drwResult = FormControlComponents.OpenSearchForm(Sys_PeriodTable.TABLE_NAME,
                                                                             Sys_PeriodTable.FROMDATE_FLD,
                                                                             WorkingPeriodText.Text.Trim(), null, true);
                if (drwResult != null)
                {
                    WorkingPeriodText.Text =
                        ((DateTime) drwResult[Sys_PeriodTable.FROMDATE_FLD]).ToString(Constants.DATETIME_FORMAT);
                    WorkingPeriodText.Tag = drwResult[Sys_PeriodTable.PERIODID_FLD];
                    WorkingPeriodLabel.Tag = drwResult[Sys_PeriodTable.TODATE_FLD];
                    WorkingPeriodButton.Tag = drwResult[Sys_PeriodTable.FROMDATE_FLD];
                }
                else
                {
                    WorkingPeriodText.Focus();
                }
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void UpdateInventoryButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".UpdateInventoryButton_Click()";
            try
            {
                if (CCNSelector.SelectedValue.Equals(null))
                {
                    PCSMessageBox.Show(ErrorCode.MESSAGE_RGA_CCN, MessageBoxIcon.Warning);
                    CCNSelector.Focus();
                    return;
                }
                var boPeriod = new StockTakingPeriodBO();
                if (PeriodText.Tag == null)
                {
                    PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                    PeriodText.Focus();
                    return;
                }
                // try to get period
                try
                {
                    var voPeriod =
                        (IV_StockTakingPeriod) boPeriod.GetObjectVO(Convert.ToInt32(PeriodText.Tag), string.Empty);
                    if (voPeriod.StockTakingPeriodID <= 0)
                    {
                        throw new Exception();
                    }
                }
                catch
                {
                    var strMessage = new string[1];
                    strMessage[0] = PeriodNameLabel.Text;
                    PCSMessageBox.Show(ErrorCode.MESSAGE_SELECTION_NOT_EXIST, MessageBoxIcon.Error, strMessage);
                    // reset data
                    PeriodText.Text = string.Empty;
                    FromDatePicker.Value = DBNull.Value;
                    ToDatePicker.Value = DBNull.Value;
                    CloseCheck.Checked = false;
                    PeriodText.Focus();
                    return;
                }

                _updateThread = new Thread(UpdateInventory)
                                    {
                                        CurrentCulture = Thread.CurrentThread.CurrentCulture,
                                        CurrentUICulture = Thread.CurrentThread.CurrentUICulture
                                    };
                _updateThread.Start();
                if (_updateThread.ThreadState == ThreadState.Stopped || !_updateThread.IsAlive)
                {
                    _updateThread.Abort();
                }
            }
            catch (ThreadAbortException ex)
            {
                Logger.LogMessage(ex, methodName, Level.DEBUG);
            }
            catch (PCSException ex)
            {
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            catch (Exception ex)
            {
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR);
                try
                {
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
        }

        private void UpdateDifferentButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".UpdateDifferentButton_Click()";
            try
            {
                if (CCNSelector.SelectedValue.Equals(null))
                {
                    PCSMessageBox.Show(ErrorCode.MESSAGE_RGA_CCN, MessageBoxIcon.Warning);
                    CCNSelector.Focus();
                    return;
                }
                var boPeriod = new StockTakingPeriodBO();
                if (PeriodText.Tag == null)
                {
                    PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                    PeriodText.Focus();
                    return;
                }
                // try to get period
                try
                {
                    var voPeriod =
                        (IV_StockTakingPeriod) boPeriod.GetObjectVO(Convert.ToInt32(PeriodText.Tag), string.Empty);
                    if (voPeriod.StockTakingPeriodID <= 0)
                    {
                        throw new Exception();
                    }
                }
                catch
                {
                    var strMessage = new string[1];
                    strMessage[0] = PeriodNameLabel.Text;
                    PCSMessageBox.Show(ErrorCode.MESSAGE_SELECTION_NOT_EXIST, MessageBoxIcon.Error, strMessage);
                    // reset data
                    PeriodText.Text = string.Empty;
                    FromDatePicker.Value = DBNull.Value;
                    ToDatePicker.Value = DBNull.Value;
                    CloseCheck.Checked = false;
                    PeriodText.Focus();
                    return;
                }

                _updateThread = new Thread(UpdateDifferent)
                                    {
                                        CurrentCulture = Thread.CurrentThread.CurrentCulture,
                                        CurrentUICulture = Thread.CurrentThread.CurrentUICulture
                                    };
                _updateThread.Start();
                if (_updateThread.ThreadState == ThreadState.Stopped || !_updateThread.IsAlive)
                {
                    _updateThread.Abort();
                }
            }
            catch (ThreadAbortException ex)
            {
                Logger.LogMessage(ex, methodName, Level.DEBUG);
            }
            catch (PCSException ex)
            {
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            catch (Exception ex)
            {
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR);
                try
                {
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
        }

        private void AddButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".AddButton_Click()";
            try
            {
                //Clear form
                ClearForm();
                //Switch form Mode
                _formMode = EnumAction.Add;
                SwitchFormMode();
                PeriodText.Focus();
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void SaveButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".SaveButton_Click()";
            try
            {
                //Validating data
                if (IsValidatingData())
                {
                    var voStockTakingPeriod = new IV_StockTakingPeriod
                                                  {
                                                      CCNID = int.Parse(CCNSelector.SelectedValue.ToString()),
                                                      Description = PeriodText.Text,
                                                      FromDate = (DateTime) FromDatePicker.Value,
                                                      ToDate = (DateTime) ToDatePicker.Value,
                                                      Closed = CloseCheck.Checked,
                                                      Approved = TakingApproved.Checked,
                                                      PeriodID = (int) WorkingPeriodText.Tag
                                                  };
                    var boStockTakingPeriod = new StockTakingPeriodBO();
                    switch (_formMode)
                    {
                        case EnumAction.Add:
                            PeriodText.Tag = voStockTakingPeriod.StockTakingPeriodID = boStockTakingPeriod.AddAndReturnID(voStockTakingPeriod);
                            break;
                        case EnumAction.Edit:
                            //add ID
                            voStockTakingPeriod.StockTakingPeriodID = (int) PeriodText.Tag;
                            boStockTakingPeriod.Update(voStockTakingPeriod);
                            break;
                    }
                    PCSMessageBox.Show(ErrorCode.MESSAGE_AFTER_SAVE_DATA);
                    SaveButton.Enabled = false;
                    _formMode = EnumAction.Default;
                    SwitchFormMode();
                }
            }
            catch (PCSException ex)
            {
                // Displays the error message if throwed from PCSException.
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                // Displays the error message if throwed from system.
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR, MessageBoxIcon.Error);
                try
                {
                    // Log error message into log file.
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    // Show message if logger has an error.
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION, MessageBoxIcon.Error);
                }
            }
        }

        private void EditButton_Click(object sender, EventArgs e)
        {
            //Switch form Mode
            _formMode = EnumAction.Edit;
            SwitchFormMode();
        }

        private void DeleteButton_Click(object sender, EventArgs e)
        {
            const string methodName = This + ".DeleteButton_Click()";
            try
            {
                if (
                    PCSMessageBox.Show(ErrorCode.MESSAGE_DELETE_RECORD, MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                    DialogResult.Yes)
                {
                    var boStockTakingPeriod = new StockTakingPeriodBO();
                    var periodId = (int) PeriodText.Tag;
                    //check before delete
                    if (boStockTakingPeriod.CheckIfDataWasUsed(periodId))
                    {
                        //delete 
                        boStockTakingPeriod.DeleteByID(periodId);
                        _formMode = EnumAction.Default;
                        ClearForm();
                        SwitchFormMode();
                    }
                    else
                    {
                        var strParam = new string[1];
                        strParam[0] = " Stock Taking Period because this Period was used to setup Stock Taking";
                        PCSMessageBox.Show(ErrorCode.MESSAGE_CAN_NOT_DELETE, MessageBoxIcon.Warning, strParam);
                        return;
                    }
                }
            }
            catch (PCSException ex)
            {
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            catch (Exception ex)
            {
                PCSMessageBox.Show(ErrorCode.OTHER_ERROR);
                try
                {
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
        }

        private void CloseButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion

        #region private methods

        /// <summary>
        /// SwitchFormMode
        /// </summary>
        /// <author>Trada</author>
        /// <date>Tuesday, July 25 2006</date>
        private void SwitchFormMode()
        {
            switch (_formMode)
            {
                case EnumAction.Default:
                    PeriodButton.Enabled = true;
                    PeriodText.Enabled = true;
                    WorkingPeriodText.Enabled = WorkingPeriodButton.Enabled = false;
                    FromDatePicker.Enabled = false;
                    ToDatePicker.Enabled = false;
                    AddButton.Enabled = true;
                    SaveButton.Enabled = false;
                    TakingApproved.Enabled = false;
                    if (PeriodText.Tag != null)
                    {
                        EditButton.Enabled = true;
                        DeleteButton.Enabled = true;
                        CloseCheck.Enabled = true;
                        UpdateInventoryButton.Enabled = TakingApproved.Checked;
                        UpdateDifferentButton.Enabled = TakingApproved.Checked;
                    }
                    else
                    {
                        EditButton.Enabled = false;
                        DeleteButton.Enabled = false;
                        CloseCheck.Enabled = false;
                        UpdateInventoryButton.Enabled = TakingApproved.Checked;
                        UpdateDifferentButton.Enabled = TakingApproved.Checked;
                    }

                    break;
                case EnumAction.Add:
                    PeriodButton.Enabled = false;
                    PeriodText.Enabled = true;
                    WorkingPeriodText.Enabled = WorkingPeriodButton.Enabled = true;
                    FromDatePicker.Enabled = true;
                    ToDatePicker.Enabled = true;
                    AddButton.Enabled = false;
                    SaveButton.Enabled = true;
                    EditButton.Enabled = false;
                    DeleteButton.Enabled = false;
                    UpdateInventoryButton.Enabled = false;
                    UpdateDifferentButton.Enabled = false;
                    CloseCheck.Enabled = true;
                    TakingApproved.Enabled = true;
                    break;
                case EnumAction.Edit:
                    PeriodButton.Enabled = false;
                    PeriodText.Enabled = true;
                    WorkingPeriodText.Enabled = WorkingPeriodButton.Enabled = true;
                    FromDatePicker.Enabled = true;
                    ToDatePicker.Enabled = true;
                    AddButton.Enabled = false;
                    SaveButton.Enabled = true;
                    EditButton.Enabled = false;
                    DeleteButton.Enabled = false;
                    CloseCheck.Enabled = true;
                    TakingApproved.Enabled = true;
                    UpdateInventoryButton.Enabled = false;
                    UpdateDifferentButton.Enabled = false;
                    break;
            }
        }

        /// <summary>
        /// Clear all control in form
        /// </summary>
        /// <author>Trada</author>
        /// <date>Tuesday, July 25 2006</date>
        private void ClearForm()
        {
            PeriodText.Text = string.Empty;
            PeriodText.Tag = null;
            WorkingPeriodText.Text = string.Empty;
            WorkingPeriodText.Tag = null;
            WorkingPeriodLabel.Tag = null;
            FromDatePicker.Value = null;
            ToDatePicker.Value = null;
            CloseCheck.Checked = false;
            TakingApproved.Checked = false;
        }

        /// <summary>
        /// Validating Data before saving
        /// </summary>
        /// <returns></returns>
        /// <author>Trada</author>
        /// <date>Tuesday, July 25 2006</date>
        private bool IsValidatingData()
        {
            if (FormControlComponents.CheckMandatory(PeriodText))
            {
                PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                PeriodText.Focus();
                return false;
            }
            if (FormControlComponents.CheckMandatory(FromDatePicker))
            {
                PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                FromDatePicker.Focus();
                return false;
            }
            if (FormControlComponents.CheckMandatory(ToDatePicker))
            {
                PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                ToDatePicker.Focus();
                return false;
            }
            if (FromDatePicker.Value != DBNull.Value && ToDatePicker.Value != DBNull.Value)
            {
                if ((DateTime) FromDatePicker.Value >= (DateTime) ToDatePicker.Value)
                {
                    PCSMessageBox.Show(ErrorCode.MESSAGE_MP_PERIODDATE, MessageBoxIcon.Warning);
                    ToDatePicker.Focus();
                    return false;
                }
            }
            if (FormControlComponents.CheckMandatory(WorkingPeriodText))
            {
                PCSMessageBox.Show(ErrorCode.MANDATORY_INVALID, MessageBoxIcon.Warning);
                WorkingPeriodText.Focus();
                return false;
            }
            return true;
        }

        /// <summary>
        ///     Fill period data to control
        /// </summary>
        /// <param name="pdrwResult"></param>
        private void FillPeriodData(DataRowView pdrwResult)
        {
            if (pdrwResult != null)
            {
                PeriodText.Text = pdrwResult[IV_StockTakingPeriodTable.DESCRIPTION_FLD].ToString();
                PeriodText.Tag = pdrwResult[IV_StockTakingPeriodTable.STOCKTAKINGPERIODID_FLD];
                CloseCheck.Checked = (bool) pdrwResult[IV_StockTakingPeriodTable.CLOSED_FLD];
                TakingApproved.Checked = (bool) pdrwResult[IV_StockTakingPeriodTable.APPROVED_FLD];
                FromDatePicker.Value = (DateTime) pdrwResult[IV_StockTakingPeriodTable.FROMDATE_FLD];
                ToDatePicker.Value = (DateTime) pdrwResult[IV_StockTakingPeriodTable.TODATE_FLD];
                DataRowView drvPeriod = FormControlComponents.OpenSearchForm(Sys_PeriodTable.TABLE_NAME,
                                                                             Sys_PeriodTable.PERIODID_FLD,
                                                                             pdrwResult[
                                                                                 IV_StockTakingPeriodTable.PERIODID_FLD]
                                                                                 .ToString(), null, false);
                WorkingPeriodText.Text =
                    ((DateTime) drvPeriod[Sys_PeriodTable.FROMDATE_FLD]).ToString(Constants.DATETIME_FORMAT);
                WorkingPeriodText.Tag = pdrwResult[IV_StockTakingPeriodTable.PERIODID_FLD];
                WorkingPeriodLabel.Tag = drvPeriod[Sys_PeriodTable.TODATE_FLD];
                WorkingPeriodButton.Tag = drvPeriod[Sys_PeriodTable.FROMDATE_FLD];
            }
            else
            {
                PeriodText.Text = string.Empty;
                PeriodText.Tag = null;
                CloseCheck.Checked = false;
                TakingApproved.Checked = false;
                FromDatePicker.Value = DateTime.Now;
                ToDatePicker.Value = DateTime.Now;
                WorkingPeriodText.Text = string.Empty;
                WorkingPeriodText.Tag = null;
                WorkingPeriodLabel.Tag = null;
                WorkingPeriodButton.Tag = null;
            }

            SwitchFormMode();
        }

        /// <summary>
        /// This will start a new thread for update inventory
        /// </summary>
        private void UpdateInventory()
        {
            const string methodName = This + ".UpdateInventory()";
            try
            {
                Cursor = Cursors.WaitCursor;
                SwitchMode(true);
                var dtmDate = (DateTime) FromDatePicker.Value;
                DateTime dtmEffectDate = Convert.ToDateTime(WorkingPeriodButton.Tag);
                UpdateInventory(Convert.ToInt32(CCNSelector.SelectedValue), Convert.ToInt32(PeriodText.Tag), dtmDate,
                                dtmEffectDate, PeriodText.Text);
                var strMsg = new[] {UpdateInventoryButton.Text.Replace("&", string.Empty)};
                PCSMessageBox.Show(ErrorCode.MESSAGE_TASK_COMPLETED, MessageBoxButtons.OK, MessageBoxIcon.Information,
                                   MessageBoxDefaultButton.Button1, strMsg);
            }
            catch (ThreadAbortException ex)
            {
                Logger.LogMessage(ex.Message, methodName, Level.DEBUG);
            }
            catch (PCSException ex)
            {
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            catch (Exception ex)
            {
                var strMsg = new[] {Text};
                PCSMessageBox.Show(ErrorCode.MESSAGE_CANNOT_ROLL_UP, MessageBoxButtons.OK, MessageBoxIcon.Warning,
                                   MessageBoxDefaultButton.Button1, strMsg);
                try
                {
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            finally
            {
                Cursor = Cursors.Default;
                SwitchMode(false);
            }
        }

        /// <summary>
        /// This will start a new thread for update inventory
        /// </summary>
        private void UpdateDifferent()
        {
            const string methodName = This + ".UpdateDifferent()";
            try
            {
                Cursor = Cursors.WaitCursor;
                SwitchMode(true);
                var dtmDate = (DateTime) FromDatePicker.Value;
                UpdateDifferent(Convert.ToInt32(PeriodText.Tag), dtmDate);
                var strMsg = new[] {UpdateDifferentButton.Text.Replace("&", string.Empty)};
                PCSMessageBox.Show(ErrorCode.MESSAGE_TASK_COMPLETED, MessageBoxButtons.OK, MessageBoxIcon.Information,
                                   MessageBoxDefaultButton.Button1, strMsg);
                Cursor = Cursors.Default;
            }
            catch (ThreadAbortException ex)
            {
                Logger.LogMessage(ex.Message, methodName, Level.DEBUG);
            }
            catch (PCSException ex)
            {
                PCSMessageBox.Show(ex.mCode, MessageBoxIcon.Error);
                try
                {
                    Logger.LogMessage(ex.CauseException, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            catch (Exception ex)
            {
                var strMsg = new[] {Text};
                PCSMessageBox.Show(ErrorCode.MESSAGE_CANNOT_ROLL_UP, MessageBoxButtons.OK, MessageBoxIcon.Warning,
                                   MessageBoxDefaultButton.Button1, strMsg);
                try
                {
                    Logger.LogMessage(ex, methodName, Level.ERROR);
                }
                catch
                {
                    PCSMessageBox.Show(ErrorCode.LOG_EXCEPTION);
                }
            }
            finally
            {
                Cursor = Cursors.Default;
                SwitchMode(false);
            }
        }

        private void UpdateInventory(int pintCcnid, int pintPeriodId, DateTime pdtmStockTakingDate,
                                     DateTime pdtmEffectDate, string pstrComment)
        {
            var boPeriod = new StockTakingPeriodBO();
            // first we will get all data of current period
            DataTable dtbStockTaking = boPeriod.GetStockTakingByPeriodID(pintPeriodId).Tables[0];
            // now get all data from all bin of current cache
            DataTable dtbCache = boPeriod.ListAllCache();
            // get all data from balance
            DataTable dtbBalance = boPeriod.ListAllBalance(pdtmEffectDate);
            // list all item in stock taking to update: based on new requirement of VBC
            DataTable dtbItemToUpdate = boPeriod.ListItemToUpdate(pintPeriodId, pdtmStockTakingDate, pdtmEffectDate);
            // list all location with master location
            DataTable dtbLocations = boPeriod.ListLocation();
            DataTable dtbAdjustmentTable = boPeriod.GetAdjustmentSchema();
            string strTransNo;
            FormInfo objFormInfo = FormControlComponents.GetFormInfo(new IVInventoryAdjustment(), out strTransNo);
            string formatNumber = objFormInfo.mTransFormat.Substring(objFormInfo.mTransFormat.IndexOf("#"));
            string strAutoNumber = strTransNo.Substring(strTransNo.Length - formatNumber.Length, formatNumber.Length);
            strTransNo = strTransNo.Substring(0, strTransNo.Length - formatNumber.Length);
            int intAutoNumber = Convert.ToInt32(strAutoNumber);
            string strComment = "Stock Taking " + pstrComment;
            var dtmToDate = (DateTime) WorkingPeriodLabel.Tag;
            foreach (DataRow drowItem in dtbItemToUpdate.Rows)
            {
                string locationId = drowItem[IV_BinCacheTable.LOCATIONID_FLD].ToString();
                string binId = drowItem[IV_BinCacheTable.BINID_FLD].ToString();
                string productId = drowItem[IV_BinCacheTable.PRODUCTID_FLD].ToString();
                string stockUmid = drowItem[ITM_ProductTable.STOCKUMID_FLD].ToString();
                string strFilter = IV_BinCacheTable.LOCATIONID_FLD + "=" + locationId
                                   + " AND " + IV_BinCacheTable.BINID_FLD + "=" + binId
                                   + " AND " + IV_BinCacheTable.PRODUCTID_FLD + "=" + productId;
                decimal decCacheQuantity = 0, decTakingQuantity = 0, decCommitQuantity = 0;
                decimal decBalanceQuantity = 0;
                // quantity from cache
                try
                {
                    decCacheQuantity = Convert.ToDecimal(dtbCache.Compute("SUM(" + IV_BinCacheTable.OHQUANTITY_FLD + ")", strFilter));
                }
                catch
                {
                }
                try
                {
                    decCommitQuantity = Convert.ToDecimal(dtbCache.Compute("SUM(" + IV_BinCacheTable.COMMITQUANTITY_FLD + ")", strFilter));
                }
                catch
                {
                }
                // quantity from stock taking
                try
                {
                    decTakingQuantity = Convert.ToDecimal(dtbStockTaking.Compute("SUM(" + IV_StockTakingTable.QUANTITY_FLD + ")",
                                                                 strFilter));
                }
                catch
                {
                }
                try
                {
                    decBalanceQuantity = Convert.ToDecimal(dtbBalance.Compute("SUM(" + IV_BalanceBinTable.OHQUANTITY_FLD + ")", strFilter));
                }
                catch
                {
                }
                // new biz here
                decimal decAdjustQuantity = decTakingQuantity - decBalanceQuantity;
                int masterLocationId = GetMasterLocation(locationId, dtbLocations);
                if (decAdjustQuantity != 0)
                {
                    intAutoNumber++;

                    #region make new adjustment record

                    DataRow drowAdjust = dtbAdjustmentTable.NewRow();
                    drowAdjust[IV_AdjustmentTable.POSTDATE_FLD] = dtmToDate;
                    drowAdjust[IV_AdjustmentTable.COMMENT_FLD] = strComment;
                    drowAdjust[IV_AdjustmentTable.PRODUCTID_FLD] = productId;
                    drowAdjust[IV_AdjustmentTable.STOCKUMID_FLD] = stockUmid;
                    drowAdjust[IV_AdjustmentTable.CCNID_FLD] = pintCcnid;
                    drowAdjust[IV_AdjustmentTable.LOCATIONID_FLD] = locationId;
                    drowAdjust[IV_AdjustmentTable.BINID_FLD] = binId;
                    drowAdjust[IV_AdjustmentTable.MASTERLOCATIONID_FLD] = masterLocationId;
                    drowAdjust[IV_AdjustmentTable.ADJUSTQUANTITY_FLD] = decAdjustQuantity;
                    drowAdjust[IV_AdjustmentTable.AVAILABLEQTY_FLD] = decCacheQuantity - decCommitQuantity;
                    drowAdjust[IV_AdjustmentTable.USEDBYCOSTING_FLD] = false;
                    drowAdjust[IV_AdjustmentTable.USERNAME_FLD] = SystemProperty.UserName;
                    drowAdjust[IV_AdjustmentTable.STOCKTAKINGPERIODID_FLD] = pintPeriodId;
                    drowAdjust[IV_AdjustmentTable.TRANSNO_FLD] = strTransNo +
                                                                 intAutoNumber.ToString().PadLeft(formatNumber.Length,
                                                                                                  '0');
                    dtbAdjustmentTable.Rows.Add(drowAdjust);

                    #endregion

                    #region update cache

                    DataRow[] drowCaches = dtbCache.Select(strFilter);
                    if (drowCaches.Length > 0)
                    {
                        // OHQuantity = OHQuantity + Adjust Quantity
                        decimal currentOnhand = 0;
                        try
                        {
                            currentOnhand = (decimal) drowCaches[0][IV_BinCacheTable.OHQUANTITY_FLD];
                        }
                        catch
                        {
                        }
                        drowCaches[0][IV_BinCacheTable.OHQUANTITY_FLD] = (currentOnhand + decAdjustQuantity) < 0
                                                                             ? 0
                                                                             : currentOnhand + decAdjustQuantity;
                    }
                    else
                    {
                        DataRow drowCache = dtbCache.NewRow();
                        drowCache[IV_BinCacheTable.CCNID_FLD] = pintCcnid;
                        drowCache[IV_BinCacheTable.MASTERLOCATIONID_FLD] = masterLocationId;
                        drowCache[IV_BinCacheTable.LOCATIONID_FLD] = locationId;
                        drowCache[IV_BinCacheTable.BINID_FLD] = binId;
                        drowCache[IV_BinCacheTable.PRODUCTID_FLD] = productId;
                        drowCache[IV_BinCacheTable.OHQUANTITY_FLD] = decAdjustQuantity < 0 ? 0 : decAdjustQuantity;
                        dtbCache.Rows.Add(drowCache);
                    }

                    #endregion
                }
            }
            boPeriod.UpdateInventory(dtbAdjustmentTable, dtbCache, strComment);
        }

        private static void UpdateDifferent(int pintPeriodId, DateTime pdtmStockTakingDate)
        {
            var boPeriod = new StockTakingPeriodBO();
            boPeriod.UpdateDifferent(pdtmStockTakingDate, pintPeriodId);
        }

        private static int GetMasterLocation(string pstrLocationId, DataTable pdtbLocation)
        {
            return Convert.ToInt32(pdtbLocation.Select(MST_LocationTable.LOCATIONID_FLD + "=" + pstrLocationId)[0][
                        MST_LocationTable.MASTERLOCATIONID_FLD]);
        }

        /// <summary>
        ///     Switch mode from processing thread
        /// </summary>
        /// <param name="processing"></param>
        private void SwitchMode(bool processing)
        {
            SetControlPropertyValue(CCNSelector, "ReadOnly", processing);
            SetControlPropertyValue(PeriodText, "Enabled", !processing);
            SetControlPropertyValue(FromDatePicker, "Enabled", !processing);
            SetControlPropertyValue(ToDatePicker, "Enabled", !processing);
            SetControlPropertyValue(CloseCheck, "Enabled", !processing);
            SetControlPropertyValue(PeriodButton, "Enabled", !processing);
            SetControlPropertyValue(AddButton, "Enabled", !processing);
            SetControlPropertyValue(EditButton, "Enabled", !processing);
            SetControlPropertyValue(DeleteButton, "Enabled", !processing);
            SetControlPropertyValue(SaveButton, "Enabled", !processing);
            SetControlPropertyValue(UpdateInventoryButton, "Enabled", !processing);
            SetControlPropertyValue(UpdateDifferentButton, "Enabled", !processing);
        }

        /// <summary>
        /// Set control property value thread-safe
        /// </summary>
        /// <param name="control"></param>
        /// <param name="propName"></param>
        /// <param name="propValue"></param>
        private void SetControlPropertyValue(Control control, string propName, object propValue)
        {
            if (control.InvokeRequired)
            {
                SetControlValueCallback d = SetControlPropertyValue;
                control.Invoke(d, new[] {control, propName, propValue});
            }
            else
            {
                Type type = control.GetType();
                PropertyInfo property = type.GetProperty(propName);
                if (property != null)
                {
                    property.SetValue(control, propValue, null);
                }
            }
        }

        private delegate void SetControlValueCallback(Control control, string propName, object propValue);

        #endregion
    }
}